{
  "cells": [
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# `parameter_estimate_comparisons_chart`"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {
        "tags": [
          "hide_input"
        ]
      },
      "outputs": [
        {
          "data": {
            "text/html": [
              "\n",
              "<style>\n",
              "  #altair-viz-8721a84a07174fc590ffcd614f22a161.vega-embed {\n",
              "    width: 100%;\n",
              "    display: flex;\n",
              "  }\n",
              "\n",
              "  #altair-viz-8721a84a07174fc590ffcd614f22a161.vega-embed details,\n",
              "  #altair-viz-8721a84a07174fc590ffcd614f22a161.vega-embed details summary {\n",
              "    position: relative;\n",
              "  }\n",
              "</style>\n",
              "<div id=\"altair-viz-8721a84a07174fc590ffcd614f22a161\"></div>\n",
              "<script type=\"text/javascript\">\n",
              "  var VEGA_DEBUG = (typeof VEGA_DEBUG == \"undefined\") ? {} : VEGA_DEBUG;\n",
              "  (function(spec, embedOpt){\n",
              "    let outputDiv = document.currentScript.previousElementSibling;\n",
              "    if (outputDiv.id !== \"altair-viz-8721a84a07174fc590ffcd614f22a161\") {\n",
              "      outputDiv = document.getElementById(\"altair-viz-8721a84a07174fc590ffcd614f22a161\");\n",
              "    }\n",
              "    const paths = {\n",
              "      \"vega\": \"https://cdn.jsdelivr.net/npm/vega@5?noext\",\n",
              "      \"vega-lib\": \"https://cdn.jsdelivr.net/npm/vega-lib?noext\",\n",
              "      \"vega-lite\": \"https://cdn.jsdelivr.net/npm/vega-lite@5.17.0?noext\",\n",
              "      \"vega-embed\": \"https://cdn.jsdelivr.net/npm/vega-embed@6?noext\",\n",
              "    };\n",
              "\n",
              "    function maybeLoadScript(lib, version) {\n",
              "      var key = `${lib.replace(\"-\", \"\")}_version`;\n",
              "      return (VEGA_DEBUG[key] == version) ?\n",
              "        Promise.resolve(paths[lib]) :\n",
              "        new Promise(function(resolve, reject) {\n",
              "          var s = document.createElement('script');\n",
              "          document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
              "          s.async = true;\n",
              "          s.onload = () => {\n",
              "            VEGA_DEBUG[key] = version;\n",
              "            return resolve(paths[lib]);\n",
              "          };\n",
              "          s.onerror = () => reject(`Error loading script: ${paths[lib]}`);\n",
              "          s.src = paths[lib];\n",
              "        });\n",
              "    }\n",
              "\n",
              "    function showError(err) {\n",
              "      outputDiv.innerHTML = `<div class=\"error\" style=\"color:red;\">${err}</div>`;\n",
              "      throw err;\n",
              "    }\n",
              "\n",
              "    function displayChart(vegaEmbed) {\n",
              "      vegaEmbed(outputDiv, spec, embedOpt)\n",
              "        .catch(err => showError(`Javascript Error: ${err.message}<br>This usually means there's a typo in your chart specification. See the javascript console for the full traceback.`));\n",
              "    }\n",
              "\n",
              "    if(typeof define === \"function\" && define.amd) {\n",
              "      requirejs.config({paths});\n",
              "      require([\"vega-embed\"], displayChart, err => showError(`Error loading script: ${err.message}`));\n",
              "    } else {\n",
              "      maybeLoadScript(\"vega\", \"5\")\n",
              "        .then(() => maybeLoadScript(\"vega-lite\", \"5.17.0\"))\n",
              "        .then(() => maybeLoadScript(\"vega-embed\", \"6\"))\n",
              "        .catch(showError)\n",
              "        .then(() => displayChart(vegaEmbed));\n",
              "    }\n",
              "  })({\"config\": {\"view\": {\"continuousWidth\": 400, \"continuousHeight\": 300}, \"title\": {\"anchor\": \"middle\", \"fontSize\": 18, \"subtitleFontSize\": 14}}, \"data\": {\"name\": \"data-6ba9d6b968af4c8b47f74558539f216e\"}, \"mark\": {\"type\": \"point\", \"filled\": false, \"opacity\": 0.7, \"size\": 100}, \"encoding\": {\"color\": {\"field\": \"estimate_description\", \"type\": \"nominal\"}, \"column\": {\"align\": \"each\", \"field\": \"col_header\", \"header\": {\"labelFontSize\": 14, \"labelFontWeight\": \"bold\"}, \"title\": null, \"type\": \"nominal\"}, \"row\": {\"align\": \"each\", \"field\": \"comparison_name\", \"header\": {\"labelAlign\": \"left\", \"labelAnchor\": \"middle\", \"labelAngle\": 0, \"labelFontSize\": 12, \"labelFontWeight\": \"bold\"}, \"sort\": {\"field\": \"comparison_sort_order\"}, \"title\": null, \"type\": \"nominal\"}, \"shape\": {\"field\": \"estimate_description\", \"scale\": {\"range\": [\"circle\", \"square\", \"triangle\", \"diamond\"]}, \"type\": \"nominal\"}, \"tooltip\": [{\"field\": \"comparison_name\", \"type\": \"nominal\"}, {\"field\": \"estimate_description\", \"type\": \"nominal\"}, {\"field\": \"estimated_probability\", \"type\": \"quantitative\"}], \"x\": {\"axis\": {\"gridColor\": {\"condition\": {\"test\": \"abs(datum.value / 10)  <= 1 & datum.value % 10 === 0\", \"value\": \"#aaa\"}, \"value\": \"#ddd\"}, \"gridDash\": {\"condition\": {\"test\": \"abs(datum.value / 10) == 1\", \"value\": [3]}, \"value\": null}, \"gridWidth\": {\"condition\": {\"test\": \"abs(datum.value / 10)  <= 1 & datum.value % 10 === 0\", \"value\": 2}, \"value\": 1}}, \"field\": \"estimated_probability_as_log_odds\", \"title\": \"Estimated probability as log odds\", \"type\": \"quantitative\"}, \"y\": {\"axis\": {\"grid\": true, \"title\": null}, \"field\": \"comparison_level_label\", \"sort\": {\"field\": \"comparison_vector_value\", \"order\": \"descending\"}, \"type\": \"nominal\"}}, \"params\": [{\"name\": \"mouse_zoom\", \"select\": {\"type\": \"interval\", \"encodings\": [\"x\"]}, \"bind\": \"scales\"}], \"resolve\": {\"scale\": {\"y\": \"independent\"}}, \"title\": {\"text\": \"Comparison of parameter estimates across training sessions\", \"subtitle\": \"Use mousewheel to zoom\"}, \"transform\": [{\"calculate\": \"datum.m_or_u + '-probability (as log odds)'\", \"as\": \"col_header\"}], \"$schema\": \"https://vega.github.io/schema/vega-lite/v5.9.3.json\", \"datasets\": {\"data-6ba9d6b968af4c8b47f74558539f216e\": [{\"m_or_u\": \"m\", \"estimated_probability\": 0.49102590159468196, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -0.05179311104678357, \"sql_condition\": \"\\\"first_name_l\\\" = \\\"first_name_r\\\"\", \"comparison_level_label\": \"Exact match on first_name\", \"comparison_vector_value\": 3, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.5117490538828517, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": 0.06781369028593094, \"sql_condition\": \"\\\"first_name_l\\\" = \\\"first_name_r\\\"\", \"comparison_level_label\": \"Exact match on first_name\", \"comparison_vector_value\": 3, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.19134183273486657, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -2.0793776591616293, \"sql_condition\": \"jaro_winkler_similarity(\\\"first_name_l\\\", \\\"first_name_r\\\") >= 0.9\", \"comparison_level_label\": \"Jaro-Winkler distance of first_name >= 0.9\", \"comparison_vector_value\": 2, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.2425823323186944, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -1.6426145938518586, \"sql_condition\": \"jaro_winkler_similarity(\\\"first_name_l\\\", \\\"first_name_r\\\") >= 0.9\", \"comparison_level_label\": \"Jaro-Winkler distance of first_name >= 0.9\", \"comparison_vector_value\": 2, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.1133899963179568, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -2.9670062745852896, \"sql_condition\": \"jaro_winkler_similarity(\\\"first_name_l\\\", \\\"first_name_r\\\") >= 0.7\", \"comparison_level_label\": \"Jaro-Winkler distance of first_name >= 0.7\", \"comparison_vector_value\": 1, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.08107634480937351, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -3.5025920524922793, \"sql_condition\": \"jaro_winkler_similarity(\\\"first_name_l\\\", \\\"first_name_r\\\") >= 0.7\", \"comparison_level_label\": \"Jaro-Winkler distance of first_name >= 0.7\", \"comparison_vector_value\": 1, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.2042422693524948, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -1.9620477946110058, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.16459226898908033, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -2.3435839215348104, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.4342319468910756, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -0.38174484480770576, \"sql_condition\": \"\\\"surname_l\\\" = \\\"surname_r\\\"\", \"comparison_level_label\": \"Exact match on surname\", \"comparison_vector_value\": 3, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.48334693557940767, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -0.09613673244447968, \"sql_condition\": \"\\\"surname_l\\\" = \\\"surname_r\\\"\", \"comparison_level_label\": \"Exact match on surname\", \"comparison_vector_value\": 3, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.2162286286680643, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -1.8578753283283775, \"sql_condition\": \"jaro_similarity(\\\"surname_l\\\", \\\"surname_r\\\") >= 0.9\", \"comparison_level_label\": \"Jaro distance of 'surname >= 0.9'\", \"comparison_vector_value\": 2, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.21908943461940666, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -1.8336374182292496, \"sql_condition\": \"jaro_similarity(\\\"surname_l\\\", \\\"surname_r\\\") >= 0.9\", \"comparison_level_label\": \"Jaro distance of 'surname >= 0.9'\", \"comparison_vector_value\": 2, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.13091545902338225, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -2.730861056748301, \"sql_condition\": \"jaro_similarity(\\\"surname_l\\\", \\\"surname_r\\\") >= 0.7\", \"comparison_level_label\": \"Jaro distance of 'surname >= 0.7'\", \"comparison_vector_value\": 1, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.1287148816706261, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -2.758966038188052, \"sql_condition\": \"jaro_similarity(\\\"surname_l\\\", \\\"surname_r\\\") >= 0.7\", \"comparison_level_label\": \"Jaro distance of 'surname >= 0.7'\", \"comparison_vector_value\": 1, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.21862396541747772, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -1.8375654506343146, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.1688487481305596, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -2.2993795577012905, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.3899696498918162, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -0.6455191731987244, \"sql_condition\": \"\\\"dob_l\\\" = \\\"dob_r\\\"\", \"comparison_level_label\": \"Exact match on dob\", \"comparison_vector_value\": 4, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.4309925914149256, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -0.4007843666248016, \"sql_condition\": \"\\\"dob_l\\\" = \\\"dob_r\\\"\", \"comparison_level_label\": \"Exact match on dob\", \"comparison_vector_value\": 4, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.14884121385473364, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -2.5156542346395256, \"sql_condition\": \"damerau_levenshtein(\\\"dob_l\\\", \\\"dob_r\\\") <= 1\", \"comparison_level_label\": \"Damerau-Levenshtein distance of dob <= 1\", \"comparison_vector_value\": 3, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.08562992852601738, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -3.416591156648649, \"sql_condition\": \"damerau_levenshtein(\\\"dob_l\\\", \\\"dob_r\\\") <= 1\", \"comparison_level_label\": \"Damerau-Levenshtein distance of dob <= 1\", \"comparison_vector_value\": 3, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.19399357567171585, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -2.054782461257593, \"sql_condition\": \"ABS(EPOCH(try_strptime(\\\"dob_l\\\", '%Y-%m-%d')) - EPOCH(try_strptime(\\\"dob_r\\\", '%Y-%m-%d'))) <= 31557600.0\", \"comparison_level_label\": \"Abs difference of 'transformed dob <= 1 year'\", \"comparison_vector_value\": 2, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.22626589252323465, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -1.773818743480876, \"sql_condition\": \"ABS(EPOCH(try_strptime(\\\"dob_l\\\", '%Y-%m-%d')) - EPOCH(try_strptime(\\\"dob_r\\\", '%Y-%m-%d'))) <= 31557600.0\", \"comparison_level_label\": \"Abs difference of 'transformed dob <= 1 year'\", \"comparison_vector_value\": 2, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": \"level not observed in training dataset\", \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": null, \"sql_condition\": \"ABS(EPOCH(try_strptime(\\\"dob_l\\\", '%Y-%m-%d')) - EPOCH(try_strptime(\\\"dob_r\\\", '%Y-%m-%d'))) <= 2629800.0\", \"comparison_level_label\": \"Abs difference of 'transformed dob <= 1 month'\", \"comparison_vector_value\": 1, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": \"level not observed in training dataset\", \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": null, \"sql_condition\": \"ABS(EPOCH(try_strptime(\\\"dob_l\\\", '%Y-%m-%d')) - EPOCH(try_strptime(\\\"dob_r\\\", '%Y-%m-%d'))) <= 2629800.0\", \"comparison_level_label\": \"Abs difference of 'transformed dob <= 1 month'\", \"comparison_vector_value\": 1, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.26719556058173427, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -1.4555322056558266, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.2571115875358224, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -1.530750891990522, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.5659765277463552, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": 0.3829691560518687, \"sql_condition\": \"\\\"city_l\\\" = \\\"city_r\\\"\", \"comparison_level_label\": \"Exact match on city\", \"comparison_vector_value\": 1, \"comparison_name\": \"city\", \"comparison_sort_order\": 3}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.5561258599237315, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": 0.32526076391144515, \"sql_condition\": \"\\\"city_l\\\" = \\\"city_r\\\"\", \"comparison_level_label\": \"Exact match on city\", \"comparison_vector_value\": 1, \"comparison_name\": \"city\", \"comparison_sort_order\": 3}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.6354674500636341, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": 0.8017705875368518, \"sql_condition\": \"\\\"city_l\\\" = \\\"city_r\\\"\", \"comparison_level_label\": \"Exact match on city\", \"comparison_vector_value\": 1, \"comparison_name\": \"city\", \"comparison_sort_order\": 3}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.4340234722536448, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -0.3829691560518689, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"city\", \"comparison_sort_order\": 3}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.4438741400762684, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -0.3252607639114453, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"city\", \"comparison_sort_order\": 3}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.36453254993636575, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -0.8017705875368525, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"city\", \"comparison_sort_order\": 3}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.5609686844538806, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": 0.35359638696035045, \"sql_condition\": \"\\\"email_l\\\" = \\\"email_r\\\"\", \"comparison_level_label\": \"Exact match on email\", \"comparison_vector_value\": 4, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.5435283839981354, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": 0.25183022291918317, \"sql_condition\": \"\\\"email_l\\\" = \\\"email_r\\\"\", \"comparison_level_label\": \"Exact match on email\", \"comparison_vector_value\": 4, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.2175129194904533, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -1.8469658377491185, \"sql_condition\": \"NULLIF(regexp_extract(\\\"email_l\\\", '^[^@]+', 0), '') = NULLIF(regexp_extract(\\\"email_r\\\", '^[^@]+', 0), '')\", \"comparison_level_label\": \"Exact match on transformed email\", \"comparison_vector_value\": 3, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.22349229688230698, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -1.7967751296786079, \"sql_condition\": \"NULLIF(regexp_extract(\\\"email_l\\\", '^[^@]+', 0), '') = NULLIF(regexp_extract(\\\"email_r\\\", '^[^@]+', 0), '')\", \"comparison_level_label\": \"Exact match on transformed email\", \"comparison_vector_value\": 3, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.19459560683703772, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -2.049234201229959, \"sql_condition\": \"jaro_winkler_similarity(\\\"email_l\\\", \\\"email_r\\\") >= 0.88\", \"comparison_level_label\": \"Jaro-Winkler distance of email >= 0.88\", \"comparison_vector_value\": 2, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.2329790387784687, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -1.7190658435315274, \"sql_condition\": \"jaro_winkler_similarity(\\\"email_l\\\", \\\"email_r\\\") >= 0.88\", \"comparison_level_label\": \"Jaro-Winkler distance of email >= 0.88\", \"comparison_vector_value\": 2, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": \"level not observed in training dataset\", \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": null, \"sql_condition\": \"jaro_winkler_similarity(NULLIF(regexp_extract(\\\"email_l\\\", '^[^@]+', 0), ''), NULLIF(regexp_extract(\\\"email_r\\\", '^[^@]+', 0), '')) >= 0.88\", \"comparison_level_label\": \"Jaro-Winkler distance of transformed email >= 0.88\", \"comparison_vector_value\": 1, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": \"level not observed in training dataset\", \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": null, \"sql_condition\": \"jaro_winkler_similarity(NULLIF(regexp_extract(\\\"email_l\\\", '^[^@]+', 0), ''), NULLIF(regexp_extract(\\\"email_r\\\", '^[^@]+', 0), '')) >= 0.88\", \"comparison_level_label\": \"Jaro-Winkler distance of transformed email >= 0.88\", \"comparison_vector_value\": 1, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.026922789218628423, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -5.175654496150526, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": 2.803410889168098e-07, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -21.76631304756658, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}]}}, {\"mode\": \"vega-lite\"});\n",
              "</script>"
            ],
            "text/plain": [
              "alt.Chart(...)"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "chart"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "!!! info \"At a glance\"\n",
        "    **Useful for:** Looking at the m and u value estimates across multiple Splink model training sessions.\n",
        "\n",
        "    **API Documentation:** [parameter_estimate_comparisons_chart()](../api_docs/visualisations.md#splink.internals.linker_components.visualisations.LinkerVisualisations.parameter_estimate_comparisons_chart)\n",
        "\n",
        "    **What is needed to generate the chart?** A trained Splink model."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Related Charts\n",
        "\n",
        "::cards::\n",
        "[\n",
        "    {\n",
        "    \"title\": \"`m u parameters chart`\",\n",
        "    \"image\": \"./img/m_u_parameters_chart.png\",\n",
        "    \"url\": \"./m_u_parameters_chart.ipynb\"\n",
        "    },\n",
        "    {\n",
        "    \"title\": \"`match weights chart`\",\n",
        "    \"image\": \"./img/match_weights_chart.png\",\n",
        "    \"url\": \"./match_weights_chart.ipynb\"\n",
        "    },\n",
        "]\n",
        "::/cards::"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Worked Example"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "tags": [
          "hide_output"
        ]
      },
      "outputs": [
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "You are using the default value for `max_pairs`, which may be too small and thus lead to inaccurate estimates for your model's u-parameters. Consider increasing to 1e8 or 1e9, which will result in more accurate estimates, but with a longer run time.\n",
            "----- Estimating u probabilities using random sampling -----\n",
            "u probability not trained for dob - Abs difference of 'transformed dob <= 1 month' (comparison vector value: 1). This usually means the comparison level was never observed in the training data.\n",
            "\n",
            "Estimated u probabilities using random sampling\n",
            "\n",
            "Your model is not yet fully trained. Missing estimates for:\n",
            "    - first_name (no m values are trained).\n",
            "    - surname (no m values are trained).\n",
            "    - dob (some u values are not trained, no m values are trained).\n",
            "    - city (no m values are trained).\n",
            "    - email (no m values are trained).\n",
            "\n",
            "----- Starting EM training session -----\n",
            "\n",
            "Estimating the m probabilities of the model by blocking on:\n",
            "(l.\"first_name\" = r.\"first_name\") AND (l.\"surname\" = r.\"surname\")\n",
            "\n",
            "Parameter estimates will be made for the following comparison(s):\n",
            "    - dob\n",
            "    - city\n",
            "    - email\n",
            "\n",
            "Parameter estimates cannot be made for the following comparison(s) since they are used in the blocking rules: \n",
            "    - first_name\n",
            "    - surname\n",
            "\n",
            "WARNING:\n",
            "Level Abs difference of 'transformed dob <= 1 month' on comparison dob not observed in dataset, unable to train m value\n",
            "\n",
            "WARNING:\n",
            "Level Jaro-Winkler distance of transformed email >= 0.88 on comparison email not observed in dataset, unable to train m value\n",
            "\n",
            "Iteration 1: Largest change in params was -0.466 in the m_probability of dob, level `Exact match on dob`\n",
            "Iteration 2: Largest change in params was 0.141 in probability_two_random_records_match\n",
            "Iteration 3: Largest change in params was 0.0319 in probability_two_random_records_match\n",
            "Iteration 4: Largest change in params was 0.0105 in probability_two_random_records_match\n",
            "Iteration 5: Largest change in params was 0.00435 in probability_two_random_records_match\n",
            "Iteration 6: Largest change in params was 0.00208 in probability_two_random_records_match\n",
            "Iteration 7: Largest change in params was 0.00109 in probability_two_random_records_match\n",
            "Iteration 8: Largest change in params was 0.000601 in probability_two_random_records_match\n",
            "Iteration 9: Largest change in params was 0.000342 in probability_two_random_records_match\n",
            "Iteration 10: Largest change in params was 0.000197 in probability_two_random_records_match\n",
            "Iteration 11: Largest change in params was 0.000115 in probability_two_random_records_match\n",
            "Iteration 12: Largest change in params was 6.75e-05 in probability_two_random_records_match\n",
            "\n",
            "EM converged after 12 iterations\n",
            "m probability not trained for dob - Abs difference of 'transformed dob <= 1 month' (comparison vector value: 1). This usually means the comparison level was never observed in the training data.\n",
            "m probability not trained for email - Jaro-Winkler distance of transformed email >= 0.88 (comparison vector value: 1). This usually means the comparison level was never observed in the training data.\n",
            "\n",
            "Your model is not yet fully trained. Missing estimates for:\n",
            "    - first_name (no m values are trained).\n",
            "    - surname (no m values are trained).\n",
            "    - dob (some u values are not trained, some m values are not trained).\n",
            "    - email (some m values are not trained).\n",
            "\n",
            "----- Starting EM training session -----\n",
            "\n",
            "Estimating the m probabilities of the model by blocking on:\n",
            "l.\"dob\" = r.\"dob\"\n",
            "\n",
            "Parameter estimates will be made for the following comparison(s):\n",
            "    - first_name\n",
            "    - surname\n",
            "    - city\n",
            "    - email\n",
            "\n",
            "Parameter estimates cannot be made for the following comparison(s) since they are used in the blocking rules: \n",
            "    - dob\n",
            "\n",
            "WARNING:\n",
            "Level Jaro-Winkler distance of transformed email >= 0.88 on comparison email not observed in dataset, unable to train m value\n",
            "\n",
            "Iteration 1: Largest change in params was 0.64 in probability_two_random_records_match\n",
            "Iteration 2: Largest change in params was 0.176 in probability_two_random_records_match\n",
            "Iteration 3: Largest change in params was 0.0846 in the m_probability of first_name, level `All other comparisons`\n",
            "Iteration 4: Largest change in params was 0.0268 in probability_two_random_records_match\n",
            "Iteration 5: Largest change in params was 0.0101 in probability_two_random_records_match\n",
            "Iteration 6: Largest change in params was 0.00431 in probability_two_random_records_match\n",
            "Iteration 7: Largest change in params was 0.00198 in probability_two_random_records_match\n",
            "Iteration 8: Largest change in params was 0.000936 in probability_two_random_records_match\n",
            "Iteration 9: Largest change in params was 0.00045 in probability_two_random_records_match\n",
            "Iteration 10: Largest change in params was 0.000218 in probability_two_random_records_match\n",
            "Iteration 11: Largest change in params was 0.000106 in probability_two_random_records_match\n",
            "Iteration 12: Largest change in params was 5.19e-05 in probability_two_random_records_match\n",
            "\n",
            "EM converged after 12 iterations\n",
            "m probability not trained for email - Jaro-Winkler distance of transformed email >= 0.88 (comparison vector value: 1). This usually means the comparison level was never observed in the training data.\n",
            "\n",
            "Your model is not yet fully trained. Missing estimates for:\n",
            "    - dob (some u values are not trained, some m values are not trained).\n",
            "    - email (some m values are not trained).\n",
            "\n",
            "----- Starting EM training session -----\n",
            "\n",
            "Estimating the m probabilities of the model by blocking on:\n",
            "l.\"email\" = r.\"email\"\n",
            "\n",
            "Parameter estimates will be made for the following comparison(s):\n",
            "    - first_name\n",
            "    - surname\n",
            "    - dob\n",
            "    - city\n",
            "\n",
            "Parameter estimates cannot be made for the following comparison(s) since they are used in the blocking rules: \n",
            "    - email\n",
            "\n",
            "WARNING:\n",
            "Level Abs difference of 'transformed dob <= 1 month' on comparison dob not observed in dataset, unable to train m value\n",
            "\n",
            "Iteration 1: Largest change in params was 0.746 in probability_two_random_records_match\n",
            "Iteration 2: Largest change in params was 0.153 in probability_two_random_records_match\n",
            "Iteration 3: Largest change in params was 0.0329 in probability_two_random_records_match\n",
            "Iteration 4: Largest change in params was 0.0107 in probability_two_random_records_match\n",
            "Iteration 5: Largest change in params was 0.00434 in probability_two_random_records_match\n",
            "Iteration 6: Largest change in params was 0.00199 in probability_two_random_records_match\n",
            "Iteration 7: Largest change in params was 0.000975 in probability_two_random_records_match\n",
            "Iteration 8: Largest change in params was 0.000494 in probability_two_random_records_match\n",
            "Iteration 9: Largest change in params was 0.000254 in probability_two_random_records_match\n",
            "Iteration 10: Largest change in params was 0.000132 in probability_two_random_records_match\n",
            "Iteration 11: Largest change in params was 6.9e-05 in probability_two_random_records_match\n",
            "\n",
            "EM converged after 11 iterations\n",
            "m probability not trained for dob - Abs difference of 'transformed dob <= 1 month' (comparison vector value: 1). This usually means the comparison level was never observed in the training data.\n",
            "\n",
            "Your model is not yet fully trained. Missing estimates for:\n",
            "    - dob (some u values are not trained, some m values are not trained).\n",
            "    - email (some m values are not trained).\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "\n",
              "<style>\n",
              "  #altair-viz-b1e6410ac72444b3ae204f20c262c927.vega-embed {\n",
              "    width: 100%;\n",
              "    display: flex;\n",
              "  }\n",
              "\n",
              "  #altair-viz-b1e6410ac72444b3ae204f20c262c927.vega-embed details,\n",
              "  #altair-viz-b1e6410ac72444b3ae204f20c262c927.vega-embed details summary {\n",
              "    position: relative;\n",
              "  }\n",
              "</style>\n",
              "<div id=\"altair-viz-b1e6410ac72444b3ae204f20c262c927\"></div>\n",
              "<script type=\"text/javascript\">\n",
              "  var VEGA_DEBUG = (typeof VEGA_DEBUG == \"undefined\") ? {} : VEGA_DEBUG;\n",
              "  (function(spec, embedOpt){\n",
              "    let outputDiv = document.currentScript.previousElementSibling;\n",
              "    if (outputDiv.id !== \"altair-viz-b1e6410ac72444b3ae204f20c262c927\") {\n",
              "      outputDiv = document.getElementById(\"altair-viz-b1e6410ac72444b3ae204f20c262c927\");\n",
              "    }\n",
              "    const paths = {\n",
              "      \"vega\": \"https://cdn.jsdelivr.net/npm/vega@5?noext\",\n",
              "      \"vega-lib\": \"https://cdn.jsdelivr.net/npm/vega-lib?noext\",\n",
              "      \"vega-lite\": \"https://cdn.jsdelivr.net/npm/vega-lite@5.17.0?noext\",\n",
              "      \"vega-embed\": \"https://cdn.jsdelivr.net/npm/vega-embed@6?noext\",\n",
              "    };\n",
              "\n",
              "    function maybeLoadScript(lib, version) {\n",
              "      var key = `${lib.replace(\"-\", \"\")}_version`;\n",
              "      return (VEGA_DEBUG[key] == version) ?\n",
              "        Promise.resolve(paths[lib]) :\n",
              "        new Promise(function(resolve, reject) {\n",
              "          var s = document.createElement('script');\n",
              "          document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
              "          s.async = true;\n",
              "          s.onload = () => {\n",
              "            VEGA_DEBUG[key] = version;\n",
              "            return resolve(paths[lib]);\n",
              "          };\n",
              "          s.onerror = () => reject(`Error loading script: ${paths[lib]}`);\n",
              "          s.src = paths[lib];\n",
              "        });\n",
              "    }\n",
              "\n",
              "    function showError(err) {\n",
              "      outputDiv.innerHTML = `<div class=\"error\" style=\"color:red;\">${err}</div>`;\n",
              "      throw err;\n",
              "    }\n",
              "\n",
              "    function displayChart(vegaEmbed) {\n",
              "      vegaEmbed(outputDiv, spec, embedOpt)\n",
              "        .catch(err => showError(`Javascript Error: ${err.message}<br>This usually means there's a typo in your chart specification. See the javascript console for the full traceback.`));\n",
              "    }\n",
              "\n",
              "    if(typeof define === \"function\" && define.amd) {\n",
              "      requirejs.config({paths});\n",
              "      require([\"vega-embed\"], displayChart, err => showError(`Error loading script: ${err.message}`));\n",
              "    } else {\n",
              "      maybeLoadScript(\"vega\", \"5\")\n",
              "        .then(() => maybeLoadScript(\"vega-lite\", \"5.17.0\"))\n",
              "        .then(() => maybeLoadScript(\"vega-embed\", \"6\"))\n",
              "        .catch(showError)\n",
              "        .then(() => displayChart(vegaEmbed));\n",
              "    }\n",
              "  })({\"config\": {\"view\": {\"continuousWidth\": 400, \"continuousHeight\": 300}, \"title\": {\"anchor\": \"middle\", \"fontSize\": 18, \"subtitleFontSize\": 14}}, \"data\": {\"name\": \"data-6ba9d6b968af4c8b47f74558539f216e\"}, \"mark\": {\"type\": \"point\", \"filled\": false, \"opacity\": 0.7, \"size\": 100}, \"encoding\": {\"color\": {\"field\": \"estimate_description\", \"type\": \"nominal\"}, \"column\": {\"align\": \"each\", \"field\": \"col_header\", \"header\": {\"labelFontSize\": 14, \"labelFontWeight\": \"bold\"}, \"title\": null, \"type\": \"nominal\"}, \"row\": {\"align\": \"each\", \"field\": \"comparison_name\", \"header\": {\"labelAlign\": \"left\", \"labelAnchor\": \"middle\", \"labelAngle\": 0, \"labelFontSize\": 12, \"labelFontWeight\": \"bold\"}, \"sort\": {\"field\": \"comparison_sort_order\"}, \"title\": null, \"type\": \"nominal\"}, \"shape\": {\"field\": \"estimate_description\", \"scale\": {\"range\": [\"circle\", \"square\", \"triangle\", \"diamond\"]}, \"type\": \"nominal\"}, \"tooltip\": [{\"field\": \"comparison_name\", \"type\": \"nominal\"}, {\"field\": \"estimate_description\", \"type\": \"nominal\"}, {\"field\": \"estimated_probability\", \"type\": \"quantitative\"}], \"x\": {\"axis\": {\"gridColor\": {\"condition\": {\"test\": \"abs(datum.value / 10)  <= 1 & datum.value % 10 === 0\", \"value\": \"#aaa\"}, \"value\": \"#ddd\"}, \"gridDash\": {\"condition\": {\"test\": \"abs(datum.value / 10) == 1\", \"value\": [3]}, \"value\": null}, \"gridWidth\": {\"condition\": {\"test\": \"abs(datum.value / 10)  <= 1 & datum.value % 10 === 0\", \"value\": 2}, \"value\": 1}}, \"field\": \"estimated_probability_as_log_odds\", \"title\": \"Estimated probability as log odds\", \"type\": \"quantitative\"}, \"y\": {\"axis\": {\"grid\": true, \"title\": null}, \"field\": \"comparison_level_label\", \"sort\": {\"field\": \"comparison_vector_value\", \"order\": \"descending\"}, \"type\": \"nominal\"}}, \"params\": [{\"name\": \"mouse_zoom\", \"select\": {\"type\": \"interval\", \"encodings\": [\"x\"]}, \"bind\": \"scales\"}], \"resolve\": {\"scale\": {\"y\": \"independent\"}}, \"title\": {\"text\": \"Comparison of parameter estimates across training sessions\", \"subtitle\": \"Use mousewheel to zoom\"}, \"transform\": [{\"calculate\": \"datum.m_or_u + '-probability (as log odds)'\", \"as\": \"col_header\"}], \"$schema\": \"https://vega.github.io/schema/vega-lite/v5.9.3.json\", \"datasets\": {\"data-6ba9d6b968af4c8b47f74558539f216e\": [{\"m_or_u\": \"m\", \"estimated_probability\": 0.49102590159468196, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -0.05179311104678357, \"sql_condition\": \"\\\"first_name_l\\\" = \\\"first_name_r\\\"\", \"comparison_level_label\": \"Exact match on first_name\", \"comparison_vector_value\": 3, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.5117490538828517, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": 0.06781369028593094, \"sql_condition\": \"\\\"first_name_l\\\" = \\\"first_name_r\\\"\", \"comparison_level_label\": \"Exact match on first_name\", \"comparison_vector_value\": 3, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.19134183273486657, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -2.0793776591616293, \"sql_condition\": \"jaro_winkler_similarity(\\\"first_name_l\\\", \\\"first_name_r\\\") >= 0.9\", \"comparison_level_label\": \"Jaro-Winkler distance of first_name >= 0.9\", \"comparison_vector_value\": 2, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.2425823323186944, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -1.6426145938518586, \"sql_condition\": \"jaro_winkler_similarity(\\\"first_name_l\\\", \\\"first_name_r\\\") >= 0.9\", \"comparison_level_label\": \"Jaro-Winkler distance of first_name >= 0.9\", \"comparison_vector_value\": 2, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.1133899963179568, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -2.9670062745852896, \"sql_condition\": \"jaro_winkler_similarity(\\\"first_name_l\\\", \\\"first_name_r\\\") >= 0.7\", \"comparison_level_label\": \"Jaro-Winkler distance of first_name >= 0.7\", \"comparison_vector_value\": 1, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.08107634480937351, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -3.5025920524922793, \"sql_condition\": \"jaro_winkler_similarity(\\\"first_name_l\\\", \\\"first_name_r\\\") >= 0.7\", \"comparison_level_label\": \"Jaro-Winkler distance of first_name >= 0.7\", \"comparison_vector_value\": 1, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.2042422693524948, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -1.9620477946110058, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.16459226898908033, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -2.3435839215348104, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"first_name\", \"comparison_sort_order\": 0}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.4342319468910756, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -0.38174484480770576, \"sql_condition\": \"\\\"surname_l\\\" = \\\"surname_r\\\"\", \"comparison_level_label\": \"Exact match on surname\", \"comparison_vector_value\": 3, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.48334693557940767, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -0.09613673244447968, \"sql_condition\": \"\\\"surname_l\\\" = \\\"surname_r\\\"\", \"comparison_level_label\": \"Exact match on surname\", \"comparison_vector_value\": 3, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.2162286286680643, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -1.8578753283283775, \"sql_condition\": \"jaro_similarity(\\\"surname_l\\\", \\\"surname_r\\\") >= 0.9\", \"comparison_level_label\": \"Jaro distance of 'surname >= 0.9'\", \"comparison_vector_value\": 2, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.21908943461940666, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -1.8336374182292496, \"sql_condition\": \"jaro_similarity(\\\"surname_l\\\", \\\"surname_r\\\") >= 0.9\", \"comparison_level_label\": \"Jaro distance of 'surname >= 0.9'\", \"comparison_vector_value\": 2, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.13091545902338225, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -2.730861056748301, \"sql_condition\": \"jaro_similarity(\\\"surname_l\\\", \\\"surname_r\\\") >= 0.7\", \"comparison_level_label\": \"Jaro distance of 'surname >= 0.7'\", \"comparison_vector_value\": 1, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.1287148816706261, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -2.758966038188052, \"sql_condition\": \"jaro_similarity(\\\"surname_l\\\", \\\"surname_r\\\") >= 0.7\", \"comparison_level_label\": \"Jaro distance of 'surname >= 0.7'\", \"comparison_vector_value\": 1, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.21862396541747772, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -1.8375654506343146, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.1688487481305596, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -2.2993795577012905, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"surname\", \"comparison_sort_order\": 1}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.3899696498918162, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -0.6455191731987244, \"sql_condition\": \"\\\"dob_l\\\" = \\\"dob_r\\\"\", \"comparison_level_label\": \"Exact match on dob\", \"comparison_vector_value\": 4, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.4309925914149256, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -0.4007843666248016, \"sql_condition\": \"\\\"dob_l\\\" = \\\"dob_r\\\"\", \"comparison_level_label\": \"Exact match on dob\", \"comparison_vector_value\": 4, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.14884121385473364, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -2.5156542346395256, \"sql_condition\": \"damerau_levenshtein(\\\"dob_l\\\", \\\"dob_r\\\") <= 1\", \"comparison_level_label\": \"Damerau-Levenshtein distance of dob <= 1\", \"comparison_vector_value\": 3, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.08562992852601738, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -3.416591156648649, \"sql_condition\": \"damerau_levenshtein(\\\"dob_l\\\", \\\"dob_r\\\") <= 1\", \"comparison_level_label\": \"Damerau-Levenshtein distance of dob <= 1\", \"comparison_vector_value\": 3, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.19399357567171585, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -2.054782461257593, \"sql_condition\": \"ABS(EPOCH(try_strptime(\\\"dob_l\\\", '%Y-%m-%d')) - EPOCH(try_strptime(\\\"dob_r\\\", '%Y-%m-%d'))) <= 31557600.0\", \"comparison_level_label\": \"Abs difference of 'transformed dob <= 1 year'\", \"comparison_vector_value\": 2, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.22626589252323465, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -1.773818743480876, \"sql_condition\": \"ABS(EPOCH(try_strptime(\\\"dob_l\\\", '%Y-%m-%d')) - EPOCH(try_strptime(\\\"dob_r\\\", '%Y-%m-%d'))) <= 31557600.0\", \"comparison_level_label\": \"Abs difference of 'transformed dob <= 1 year'\", \"comparison_vector_value\": 2, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": \"level not observed in training dataset\", \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": null, \"sql_condition\": \"ABS(EPOCH(try_strptime(\\\"dob_l\\\", '%Y-%m-%d')) - EPOCH(try_strptime(\\\"dob_r\\\", '%Y-%m-%d'))) <= 2629800.0\", \"comparison_level_label\": \"Abs difference of 'transformed dob <= 1 month'\", \"comparison_vector_value\": 1, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": \"level not observed in training dataset\", \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": null, \"sql_condition\": \"ABS(EPOCH(try_strptime(\\\"dob_l\\\", '%Y-%m-%d')) - EPOCH(try_strptime(\\\"dob_r\\\", '%Y-%m-%d'))) <= 2629800.0\", \"comparison_level_label\": \"Abs difference of 'transformed dob <= 1 month'\", \"comparison_vector_value\": 1, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.26719556058173427, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -1.4555322056558266, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.2571115875358224, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -1.530750891990522, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"dob\", \"comparison_sort_order\": 2}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.5659765277463552, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": 0.3829691560518687, \"sql_condition\": \"\\\"city_l\\\" = \\\"city_r\\\"\", \"comparison_level_label\": \"Exact match on city\", \"comparison_vector_value\": 1, \"comparison_name\": \"city\", \"comparison_sort_order\": 3}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.5561258599237315, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": 0.32526076391144515, \"sql_condition\": \"\\\"city_l\\\" = \\\"city_r\\\"\", \"comparison_level_label\": \"Exact match on city\", \"comparison_vector_value\": 1, \"comparison_name\": \"city\", \"comparison_sort_order\": 3}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.6354674500636341, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": 0.8017705875368518, \"sql_condition\": \"\\\"city_l\\\" = \\\"city_r\\\"\", \"comparison_level_label\": \"Exact match on city\", \"comparison_vector_value\": 1, \"comparison_name\": \"city\", \"comparison_sort_order\": 3}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.4340234722536448, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -0.3829691560518689, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"city\", \"comparison_sort_order\": 3}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.4438741400762684, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -0.3252607639114453, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"city\", \"comparison_sort_order\": 3}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.36453254993636575, \"estimate_description\": \"EM, blocked on: l.\\\"email\\\" = r.\\\"email\\\"\", \"estimated_probability_as_log_odds\": -0.8017705875368525, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"city\", \"comparison_sort_order\": 3}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.5609686844538806, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": 0.35359638696035045, \"sql_condition\": \"\\\"email_l\\\" = \\\"email_r\\\"\", \"comparison_level_label\": \"Exact match on email\", \"comparison_vector_value\": 4, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.5435283839981354, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": 0.25183022291918317, \"sql_condition\": \"\\\"email_l\\\" = \\\"email_r\\\"\", \"comparison_level_label\": \"Exact match on email\", \"comparison_vector_value\": 4, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.2175129194904533, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -1.8469658377491185, \"sql_condition\": \"NULLIF(regexp_extract(\\\"email_l\\\", '^[^@]+', 0), '') = NULLIF(regexp_extract(\\\"email_r\\\", '^[^@]+', 0), '')\", \"comparison_level_label\": \"Exact match on transformed email\", \"comparison_vector_value\": 3, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.22349229688230698, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -1.7967751296786079, \"sql_condition\": \"NULLIF(regexp_extract(\\\"email_l\\\", '^[^@]+', 0), '') = NULLIF(regexp_extract(\\\"email_r\\\", '^[^@]+', 0), '')\", \"comparison_level_label\": \"Exact match on transformed email\", \"comparison_vector_value\": 3, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.19459560683703772, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -2.049234201229959, \"sql_condition\": \"jaro_winkler_similarity(\\\"email_l\\\", \\\"email_r\\\") >= 0.88\", \"comparison_level_label\": \"Jaro-Winkler distance of email >= 0.88\", \"comparison_vector_value\": 2, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.2329790387784687, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -1.7190658435315274, \"sql_condition\": \"jaro_winkler_similarity(\\\"email_l\\\", \\\"email_r\\\") >= 0.88\", \"comparison_level_label\": \"Jaro-Winkler distance of email >= 0.88\", \"comparison_vector_value\": 2, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": \"level not observed in training dataset\", \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": null, \"sql_condition\": \"jaro_winkler_similarity(NULLIF(regexp_extract(\\\"email_l\\\", '^[^@]+', 0), ''), NULLIF(regexp_extract(\\\"email_r\\\", '^[^@]+', 0), '')) >= 0.88\", \"comparison_level_label\": \"Jaro-Winkler distance of transformed email >= 0.88\", \"comparison_vector_value\": 1, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": \"level not observed in training dataset\", \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": null, \"sql_condition\": \"jaro_winkler_similarity(NULLIF(regexp_extract(\\\"email_l\\\", '^[^@]+', 0), ''), NULLIF(regexp_extract(\\\"email_r\\\", '^[^@]+', 0), '')) >= 0.88\", \"comparison_level_label\": \"Jaro-Winkler distance of transformed email >= 0.88\", \"comparison_vector_value\": 1, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": 0.026922789218628423, \"estimate_description\": \"EM, blocked on: (l.\\\"first_name\\\" = r.\\\"first_name\\\") AND (l.\\\"surname\\\" = r.\\\"surname\\\")\", \"estimated_probability_as_log_odds\": -5.175654496150526, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}, {\"m_or_u\": \"m\", \"estimated_probability\": 2.803410889168098e-07, \"estimate_description\": \"EM, blocked on: l.\\\"dob\\\" = r.\\\"dob\\\"\", \"estimated_probability_as_log_odds\": -21.76631304756658, \"sql_condition\": \"ELSE\", \"comparison_level_label\": \"All other comparisons\", \"comparison_vector_value\": 0, \"comparison_name\": \"email\", \"comparison_sort_order\": 4}]}}, {\"mode\": \"vega-lite\"});\n",
              "</script>"
            ],
            "text/plain": [
              "alt.Chart(...)"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "import splink.comparison_library as cl\n",
        "from splink import DuckDBAPI, Linker, SettingsCreator, block_on, splink_datasets\n",
        "\n",
        "df = splink_datasets.fake_1000\n",
        "\n",
        "settings = SettingsCreator(\n",
        "    link_type=\"dedupe_only\",\n",
        "    comparisons=[\n",
        "        cl.JaroWinklerAtThresholds(\"first_name\", [0.9, 0.7]),\n",
        "        cl.JaroAtThresholds(\"surname\", [0.9, 0.7]),\n",
        "        cl.DateOfBirthComparison(\n",
        "            \"dob\",\n",
        "            input_is_string=True,\n",
        "            datetime_metrics=[\"year\", \"month\"],\n",
        "            datetime_thresholds=[1, 1],\n",
        "        ),\n",
        "        cl.ExactMatch(\"city\").configure(term_frequency_adjustments=True),\n",
        "        cl.EmailComparison(\"email\"),\n",
        "    ],\n",
        "    blocking_rules_to_generate_predictions=[\n",
        "        block_on(\"first_name\"),\n",
        "        block_on(\"surname\"),\n",
        "    ],\n",
        ")\n",
        "\n",
        "linker = Linker(df, settings, DuckDBAPI())\n",
        "linker.training.estimate_u_using_random_sampling(max_pairs=1e6)\n",
        "\n",
        "blocking_rule_for_training = block_on(\"first_name\", \"surname\")\n",
        "linker.training.estimate_parameters_using_expectation_maximisation(\n",
        "    blocking_rule_for_training\n",
        ")\n",
        "\n",
        "blocking_rule_for_training = block_on(\"dob\")\n",
        "linker.training.estimate_parameters_using_expectation_maximisation(\n",
        "    blocking_rule_for_training\n",
        ")\n",
        "\n",
        "blocking_rule_for_training = block_on(\"email\")\n",
        "linker.training.estimate_parameters_using_expectation_maximisation(\n",
        "    blocking_rule_for_training\n",
        ")\n",
        "\n",
        "chart = linker.visualisations.parameter_estimate_comparisons_chart()\n",
        "chart\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": []
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "base",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.10.8"
    },
    "orig_nbformat": 4
  },
  "nbformat": 4,
  "nbformat_minor": 2
}
